package com.xiaoyu.pay

import `in`.srain.cube.request.JsonData
import `in`.srain.cube.util.CLog
import `in`.srain.cube.util.JSONUtils
import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.text.TextUtils
import com.alipay.sdk.app.PayTask
import com.tencent.mm.opensdk.modelbiz.WXOpenBusinessWebview
import com.tencent.mm.opensdk.modelpay.PayReq
import com.tencent.mm.opensdk.openapi.IWXAPI
import com.tencent.mm.opensdk.openapi.WXAPIFactory
import com.xiaoyu.pay.event.PayEvent
import com.xiaoyu.base.AppConfig
import com.xiaoyu.base.app.App
import com.xiaoyu.base.app.AppContext
import com.xiaoyu.base.app.GlobalUI
import `in`.srain.cube.util.UTUtil
import com.xiaoyu.base.utils.RxUtils
import io.reactivex.Single
import io.reactivex.SingleEmitter
import java.lang.ref.WeakReference
import java.util.*

class PayUtil {

    companion object {
        private val ALI_SIGN_PAGE_PREFIX = "alipays://platformapi/startapp?appId=${AppConfig.aliPayAppId()}&appClearTop=false&startMultApp=YES&sign_params="
        private const val WE_CHAT_BUSINESS_TYPE = 12

        @JvmField
        val WE_CHAT_NO_INSTALLED_STRING: String = AppContext.getString(R.string.wechat_not_installed)
    }

    private var mAliPayTask: PayTask? = null
    private var mWeChatIWXAPI: IWXAPI? = null
    private var mWeChatPayReq: PayReq? = null

    @SuppressLint("CheckResult")
    fun toAliPay(data: String) {
        createAliPay(data)
                .compose(RxUtils.ioToMainSingleScheduler())
                .subscribe({ aliPayResult: AliPayResult ->
                    var isSuccess = false
                    when (aliPayResult.resultStatus) {
                        "9000" -> {
                            isSuccess = true
                            CLog.i("AliPay", "订单支付成功")
                        }
                        "8000" -> CLog.i("AliPay", "正在处理中，支付结果未知（有可能已经支付成功），请查询商户订单列表中订单的支付状态")
                        "4000" -> {
                            CLog.i("AliPay", "订单支付失败")
                            logForAliPayFail("4000")
                        }
                        "5000" -> {
                            CLog.i("AliPay", "重复请求")
                            logForAliPayFail("5000")
                        }
                        "6001" -> {
                            CLog.i("AliPay", "用户中途取消")
                            logForAliPayFail("6001")
                        }
                        "6002" -> {
                            CLog.i("AliPay", "网络连接出错")
                            logForAliPayFail("6002")
                        }
                        "6004" -> {
                            CLog.i("AliPay", "支付结果未知（有可能已经支付成功），请查询商户订单列表中订单的支付状态")
                            logForAliPayFail("6004")
                        }
                        else -> {
                            CLog.i("AliPay", "其它支付错误")
                            logForAliPayFail("")
                        }
                    }
                    aliPayResult.resultStatus?.let {
                        PayEvent(ALI_PAY, isSuccess, it).post()
                    }
                }) { throwable: Throwable? ->
                    PayEvent(ALI_PAY, false, "").post()
                    throwable?.printStackTrace()
                }
    }

    @SuppressLint("CheckResult")
    fun toWeChatPay(data: String) {
        createWeChatPay(data)
                .compose<JsonData>(RxUtils.ioToMainSingleScheduler<JsonData>())
                .subscribe({ jsonData: JsonData ->
                    val weChatPayModel = WeChatPayModel(jsonData)
                    if (TextUtils.equals(weChatPayModel.mAppid, AppConfig.wechatAppId())) {
                        mWeChatPayReq?.appId = weChatPayModel.mAppid
                        mWeChatPayReq?.partnerId = weChatPayModel.mPartnerId
                        mWeChatPayReq?.prepayId = weChatPayModel.mPrepayId
                        mWeChatPayReq?.packageValue = weChatPayModel.mPackage
                        mWeChatPayReq?.nonceStr = weChatPayModel.mNonceStr
                        mWeChatPayReq?.timeStamp = weChatPayModel.mTimestamp.toString()
                        mWeChatPayReq?.sign = weChatPayModel.mSign
                        mWeChatIWXAPI?.registerApp(weChatPayModel.mAppid)
                        mWeChatIWXAPI?.sendReq(mWeChatPayReq)
                    }
                }) { throwable: Throwable? ->
                    PayEvent(WE_CHAT_PAY, false, "").post()
                    throwable?.printStackTrace()
                }
    }

    fun toAliSignPage(params: String) {
        val activity = App.getInstance().topActivity ?: return
        val uri = Uri.parse(ALI_SIGN_PAGE_PREFIX + params)
        val intent = Intent(Intent.ACTION_VIEW, uri)
        if (intent.resolveActivity(activity.packageManager) != null) {
            activity.startActivity(intent)
        }
    }

    @SuppressLint("CheckResult")
    fun toWeChatSignPage(params: String) {
        createWeChatPay(params)
                .compose<JsonData>(RxUtils.ioToMainSingleScheduler<JsonData>())
                .subscribe({ jsonData: JsonData? ->
                    val map = JSONUtils.toMap(jsonData, String::class.java) as HashMap<String, String?>
                    val req = WXOpenBusinessWebview.Req()
                    req.businessType = WE_CHAT_BUSINESS_TYPE
                    req.queryInfo = map
                    mWeChatIWXAPI?.sendReq(req)
                }) { throwable: Throwable? ->
                    PayEvent(WE_CHAT_PAY, false, "").post()
                    throwable?.printStackTrace()
                }
    }

    private fun logForAliPayFail(statusCode: String) {
        val params = Bundle()
        params.putString("status_code", statusCode)
        UTUtil.getInstance().logEvent("vip_buy_failed", params)
    }

    private fun initAliPay() {
        val activity = App.getInstance().topActivity ?: return
        val activityWeakReference = WeakReference(activity)
        if (activityWeakReference.get() == null) {
            return
        }
        mAliPayTask = PayTask(activityWeakReference.get())
    }

    private fun initWeChatPay() {
        mWeChatIWXAPI = WXAPIFactory.createWXAPI(AppContext.getContext(), AppConfig.wechatAppId(), true)
        mWeChatIWXAPI?.registerApp(AppConfig.wechatAppId())
        mWeChatPayReq = PayReq()
    }

    private fun createAliPay(params: String): Single<AliPayResult> {
        return Single.create { emitter: SingleEmitter<AliPayResult> ->
            if (mAliPayTask == null) {
                initAliPay()
            }
            if (mAliPayTask == null) {
                emitter.onError(Throwable("top activity null"))
            } else {
                mAliPayTask?.let {
                    val aliPayResult = AliPayResult(it.payV2(params, true))
                    emitter.onSuccess(aliPayResult)
                }
            }
        }
    }

    private fun createWeChatPay(params: String): Single<JsonData> {
        return Single.create<JsonData> { emitter: SingleEmitter<JsonData> ->
            if (mWeChatIWXAPI == null || mWeChatPayReq == null) {
                initWeChatPay()
            }
            if (mWeChatIWXAPI?.isWXAppInstalled != true) {
                GlobalUI.getInstance().showToast(WE_CHAT_NO_INSTALLED_STRING)
                emitter.onError(Throwable("isWXAppInstalled false"))
            } else {
                val jsonData: JsonData = JsonData.create(params)
                emitter.onSuccess(jsonData)
            }
        }
    }

    fun destroy() {
        mWeChatIWXAPI?.unregisterApp()
        mWeChatIWXAPI?.detach()
        mWeChatPayReq = null
        mAliPayTask = null
    }
}